"""用户控制器"""
import logging
from typing import Optional, Dict, Any
from datetime import timedelta
from sqlalchemy.orm import Session
from sqlalchemy import desc
from app.models.user import User
from app.models.video import Video
from app.models.follow import Follow
from app.models.like import Like
from app.models.favorite import Favorite
from app.schemas.user import UserCreate, UserUpdate, TokenResponse
from app.config.auth import (
    get_password_hash,
    verify_password,
    create_access_token,
    ALGORITHM,
    SECRET_KEY
)
from jose import JWTError, jwt

logger = logging.getLogger(__name__)


class UserController:
    """用户控制器类"""
    
    @staticmethod
    def create_user(db: Session, user_data: UserCreate) -> User:
        """创建新用户"""
        # 检查用户名是否已存在
        existing_user = db.query(User).filter(
            User.username == user_data.username
        ).first()
        
        if existing_user:
            raise ValueError("用户名已存在")
        
        # 检查邮箱是否已存在
        if user_data.email:
            existing_email = db.query(User).filter(
                User.email == user_data.email
            ).first()
            if existing_email:
                raise ValueError("邮箱已被注册")
        
        # 创建新用户
        hashed_password = get_password_hash(user_data.password)
        db_user = User(
            username=user_data.username,
            password=hashed_password,
            nickname=user_data.nickname or user_data.username,
            email=user_data.email,
            avatar=user_data.avatar,
            gender=user_data.gender,
            bio=user_data.bio
        )
        
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        
        return db_user
    
    @staticmethod
    def authenticate_user(db: Session, username: str, password: str) -> Optional[User]:
        """用户认证"""
        user = db.query(User).filter(User.username == username).first()
        if not user:
            return None
        if not verify_password(password, user.password):
            return None
        return user
    
    @staticmethod
    def login(db: Session, username: str, password: str) -> TokenResponse:
        """用户登录"""
        user = UserController.authenticate_user(db, username, password)
        if not user:
            raise ValueError("用户名或密码错误")
        
        # 创建访问令牌
        access_token_expires = timedelta(days=7)  # 7天过期
        access_token = create_access_token(
            data={"sub": str(user.id), "username": user.username},
            expires_delta=access_token_expires
        )
        
        return TokenResponse(
            access_token=access_token,
            token_type="bearer",
            user_id=user.id,
            username=user.username,
            nickname=user.nickname,
            avatar=user.avatar
        )
    
    @staticmethod
    def get_user_by_id(db: Session, user_id: int) -> Optional[User]:
        """根据ID获取用户"""
        return db.query(User).filter(User.id == user_id).first()
    
    @staticmethod
    def get_user_by_username(db: Session, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        return db.query(User).filter(User.username == username).first()
    
    @staticmethod
    def update_user(db: Session, user_id: int, user_update: UserUpdate) -> Optional[User]:
        """更新用户信息"""
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            return None
        
        # 更新用户信息
        update_data = user_update.dict(exclude_unset=True)
        
        # 如果更新密码，需要重新哈希
        if "password" in update_data:
            update_data["password"] = get_password_hash(update_data["password"])
        
        # 检查邮箱是否被其他用户使用
        if "email" in update_data and update_data["email"]:
            existing_email = db.query(User).filter(
                User.email == update_data["email"],
                User.id != user_id
            ).first()
            if existing_email:
                raise ValueError("邮箱已被其他用户使用")
        
        for field, value in update_data.items():
            setattr(user, field, value)
        
        db.commit()
        db.refresh(user)
        
        return user
    
    @staticmethod
    def get_user_profile(db: Session, user_id: int, current_user_id: Optional[int] = None) -> Dict[str, Any]:
        """获取用户资料"""
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            return None
        
        # 获取用户统计信息
        # 视频数量
        video_count = db.query(Video).filter(Video.user_id == user_id, Video.status == 1).count()
        
        # 粉丝数量
        follower_count = db.query(Follow).filter(Follow.following_id == user_id).count()
        
        # 关注数量
        following_count = db.query(Follow).filter(Follow.follower_id == user_id).count()
        
        # 如果当前用户已登录，检查是否已关注该用户
        is_followed = False
        if current_user_id and current_user_id != user_id:
            follow = db.query(Follow).filter(
                Follow.follower_id == current_user_id,
                Follow.following_id == user_id
            ).first()
            is_followed = follow is not None
        
        # 构建用户资料
        user_profile = {
            "id": user.id,
            "username": user.username,
            "nickname": user.nickname,
            "avatar": user.avatar,
            "email": user.email,
            "gender": user.gender,
            "bio": user.bio,
            "created_at": user.created_at.isoformat() if user.created_at else None,
            "video_count": video_count,
            "follower_count": follower_count,
            "following_count": following_count,
            "is_followed": is_followed
        }
        
        return user_profile
    
    @staticmethod
    def get_user_videos(db: Session, user_id: int, page: int = 1, pageSize: int = 10) -> Dict[str, Any]:
        """获取用户发布的视频列表"""
        # 验证参数
        if user_id <= 0:
            raise ValueError("用户ID无效")
        if page < 1:
            page = 1
        if pageSize < 1 or pageSize > 50:
            pageSize = 10
        
        offset = (page - 1) * pageSize
        limit = pageSize
        
        # 查询数据库
        query = db.query(Video).filter(Video.user_id == user_id, Video.status == 1)
        total = query.count()
        
        # 获取视频列表
        videos = query.order_by(desc(Video.created_at)).offset(offset).limit(limit).all()
        
        # 转换为响应格式
        videos_data = []
        for video in videos:
            video_dict = {
                "id": video.id,
                "title": video.title,
                "description": video.description,
                "cover_url": video.cover_url,
                "video_url": video.video_url,
                "duration": video.duration,
                "category_id": video.category_id,
                "user_id": video.user_id,
                "view_count": video.view_count,
                "like_count": video.like_count,
                "collect_count": video.collect_count,
                "comment_count": video.comment_count,
                "publish_time": video.publish_time.isoformat() if video.publish_time else None
            }
            videos_data.append(video_dict)
        
        total_pages = (total + pageSize - 1) // pageSize
        return {
            "list": videos_data,
            "total": total,
            "page": page,
            "pageSize": pageSize,
            "totalPages": total_pages
        }
    
    @staticmethod
    def get_user_liked_videos(db: Session, user_id: int, page: int = 1, pageSize: int = 10) -> Dict[str, Any]:
        """获取用户点赞的视频列表"""
        # 验证参数
        if user_id <= 0:
            raise ValueError("用户ID无效")
        if page < 1:
            page = 1
        if pageSize < 1 or pageSize > 50:
            pageSize = 10
        
        offset = (page - 1) * pageSize
        limit = pageSize
        
        # 查询数据库
        query = db.query(Video).join(
            Like, Video.id == Like.video_id
        ).filter(
            Like.user_id == user_id,
            Video.status == 1
        )
        total = query.count()
        
        # 获取视频列表
        videos = query.order_by(desc(Like.created_at)).offset(offset).limit(limit).all()
        
        # 转换为响应格式
        videos_data = []
        for video in videos:
            video_dict = {
                "id": video.id,
                "title": video.title,
                "description": video.description,
                "cover_url": video.cover_url,
                "video_url": video.video_url,
                "duration": video.duration,
                "category_id": video.category_id,
                "user_id": video.user_id,
                "view_count": video.view_count,
                "like_count": video.like_count,
                "collect_count": video.collect_count,
                "comment_count": video.comment_count,
                "publish_time": video.publish_time.isoformat() if video.publish_time else None
            }
            videos_data.append(video_dict)
        
        total_pages = (total + pageSize - 1) // pageSize
        return {
            "list": videos_data,
            "total": total,
            "page": page,
            "pageSize": pageSize,
            "totalPages": total_pages
        }
    
    @staticmethod
    def get_user_favorite_videos(db: Session, user_id: int, page: int = 1, pageSize: int = 10) -> Dict[str, Any]:
        """获取用户收藏的视频列表"""
        # 验证参数
        if user_id <= 0:
            raise ValueError("用户ID无效")
        if page < 1:
            page = 1
        if pageSize < 1 or pageSize > 50:
            pageSize = 10
        
        offset = (page - 1) * pageSize
        limit = pageSize
        
        # 查询数据库
        query = db.query(Video).join(
            Favorite, Video.id == Favorite.video_id
        ).filter(
            Favorite.user_id == user_id,
            Video.status == 1
        )
        total = query.count()
        
        # 获取视频列表
        videos = query.order_by(desc(Favorite.created_at)).offset(offset).limit(limit).all()
        
        # 转换为响应格式
        videos_data = []
        for video in videos:
            video_dict = {
                "id": video.id,
                "title": video.title,
                "description": video.description,
                "cover_url": video.cover_url,
                "video_url": video.video_url,
                "duration": video.duration,
                "category_id": video.category_id,
                "user_id": video.user_id,
                "view_count": video.view_count,
                "like_count": video.like_count,
                "collect_count": video.collect_count,
                "comment_count": video.comment_count,
                "publish_time": video.publish_time.isoformat() if video.publish_time else None
            }
            videos_data.append(video_dict)
        
        total_pages = (total + pageSize - 1) // pageSize
        return {
            "list": videos_data,
            "total": total,
            "page": page,
            "pageSize": pageSize,
            "totalPages": total_pages
        }
    
    @staticmethod
    def follow_user(db: Session, follower_id: int, following_id: int) -> bool:
        """关注用户"""
        # 不能关注自己
        if follower_id == following_id:
            raise ValueError("不能关注自己")
        
        # 检查被关注用户是否存在
        following_user = db.query(User).filter(User.id == following_id).first()
        if not following_user:
            raise ValueError("被关注用户不存在")
        
        # 检查是否已经关注
        existing_follow = db.query(Follow).filter(
            Follow.follower_id == follower_id,
            Follow.following_id == following_id
        ).first()
        
        if existing_follow:
            return True  # 已经关注了，直接返回True
        
        # 创建关注关系
        follow = Follow(
            follower_id=follower_id,
            following_id=following_id
        )
        
        db.add(follow)
        db.commit()
        
        return True
    
    @staticmethod
    def unfollow_user(db: Session, follower_id: int, following_id: int) -> bool:
        """取消关注用户"""
        # 查找关注关系
        follow = db.query(Follow).filter(
            Follow.follower_id == follower_id,
            Follow.following_id == following_id
        ).first()
        
        if not follow:
            return True  # 没有关注关系，直接返回True
        
        # 删除关注关系
        db.delete(follow)
        db.commit()
        
        return True


# 创建全局用户控制器实例
user_controller = UserController()
